use crate::error::AppResult;

/// 获得 casbin policies.
/// # params
/// - role_id 可选，过滤对应的role
/// - resource_id 可选，过滤对应的resource
pub async fn casbin_policies(
    db: &sea_orm::DbConn,
    role_id: Option<i32>,
    resource_id: Option<i32>,
) -> AppResult<Vec<Vec<String>>> {
    Ok(ane_system::casbin_policies(db, role_id, resource_id)
        .await?
        .into_iter()
        .map(|f| {
            vec![
                format!("role_{}", f.0),
                f.1,
                f.2,
                if f.3 { "allow" } else { "deny" }.to_owned(),
            ]
        })
        .collect::<Vec<_>>())
}

/// 根据key从[serde_json::Value]中获取[serde_json::Value]
pub fn get_json_key(key: &str, data: &serde_json::Value) -> Option<serde_json::Value> {
    if let Some(v) = data.get(key) {
        return Some(v.clone());
    }
    if let Some(v) = data.as_array() {
        if let Ok(i) = key.parse::<usize>() {
            return v.get(i).cloned();
        }
    }
    data.as_object().and_then(|data| {
        key.split_once(".")
            .and_then(|(key1, key2)| data.get(key1).and_then(|v| get_json_key(key2, v)))
    })
}

/// 根据key从[tera::Context]中获取[serde_json::Value]
pub fn get_context_key(key: &str, cxt: &tera::Context) -> Option<serde_json::Value> {
    if let Some(v) = cxt.get(key) {
        return Some(v.clone());
    }
    key.split_once(".")
        .and_then(|(key1, key2)| cxt.get(key1).and_then(|v| get_json_key(key2, v)))
}
